package hotel.compare.oversea.service.impl;

import hotel.base.oversea.constant.CommonConstants;
import hotel.base.oversea.service.impl.BaseServiceImpl;
import hotel.base.oversea.utils.CompareUtil;
import hotel.base.oversea.utils.Result;
import hotel.compare.oversea.config.service.RedisService;
import hotel.compare.oversea.entity.master.CompareHotelRoom;
import hotel.compare.oversea.entity.master.CompareHotelRoomBed;
import hotel.compare.oversea.entity.meituan.MtHotelRoomBedInfo;
import hotel.compare.oversea.entity.switchs.SwitchRoomBedInfo;
import hotel.compare.oversea.mapper.master.CompareHotelRoomBedMapper;
import hotel.compare.oversea.mapper.meituan.MtHotelRoomBedInfoMapper;
import hotel.compare.oversea.mapper.switchs.SwitchRoomBedInfoMapper;
import hotel.compare.oversea.service.CompareHotelRoomBedService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.ObjectUtils;
import org.springframework.util.StringUtils;

import java.util.*;
import java.util.concurrent.*;

/**
 * 校验床型信息
 * @Author lmf
 * @Date 2020/5/29 13:55
 **/
@Service
@Slf4j
public class CompareHotelRoomBedServiceImpl extends BaseServiceImpl<CompareHotelRoomBed> implements CompareHotelRoomBedService {

    @Autowired
    private RedisService redisService;

    @Autowired
    private CompareHotelRoomBedMapper compareHotelRoomBedMapper;

    @Autowired
    private SwitchRoomBedInfoMapper switchRoomBedInfoMapper;

    @Autowired
    private MtHotelRoomBedInfoMapper mtHotelRoomBedInfoMapper;


    /**
    *@Description:
     * 效验床型信息 -- 多线程 --备用
     * @return
     * 1.获取已经匹配的房型id
     * 2.获取床型
     * 3.进行匹配
     * 4.保存入库
    *@Author: Zhang·jz
    *@date: 2020/9/19
    */
    public Result<Object> compareHotelRoomBedThread() throws InterruptedException, ExecutionException {
        Map<String, CompareHotelRoom> compareHotelRooms= (Map<String, CompareHotelRoom>) redisService.get(CommonConstants.COMPARE_ROOM_ID);
        if(ObjectUtils.isEmpty(compareHotelRooms)){
            log.info("暂无匹配房型信息可对比");
            return new Result<>("暂无匹配房型信息可对比");
        }

        List<CompareHotelRoom> compareHotelRoomList = new ArrayList<>();
        compareHotelRooms.values().forEach(compareHotelRoom -> {
            compareHotelRoomList.add(compareHotelRoom);
        });


        StringBuffer ret = new StringBuffer();
        // 总数
        int dataSize = compareHotelRoomList.size();
        // 线程数
        int threadNum = 10;
        // 每500条数据开启一条线程
        int num = 0;
        if((dataSize%threadNum) > 0){
            num = 1;
        }
        int threadSize = dataSize/threadNum + num;
        // 定义标记,过滤threadNum为整数
        boolean special = dataSize % threadSize == 0;

        // 创建一个线程池
        ExecutorService exec = Executors.newFixedThreadPool(threadNum);
        // 定义一个任务集合
        List<Callable<Integer>> tasks = new ArrayList<Callable<Integer>>();
        Callable<Integer> task = null;
        List<CompareHotelRoom> cutList = new ArrayList<>();

        //如果数量小直接执行
        if(dataSize<= threadNum){
            final String taskNum = String.valueOf(1);
            task = new Callable<Integer>() {
                @Override
                public Integer call() throws Exception {

                    Thread.sleep(10);
                    compareHotelRoomBadByThread(taskNum,compareHotelRoomList);
                    return 1;
                }
            };
            // 这里提交的任务容器列表和返回的Future列表存在顺序对应的关系
            tasks.add(task);
        }else {
            // 确定每条线程的数据
            for (int i = 0; i < threadNum; i++) {
                if (i == threadNum - 1) {
                    if (special) {
                        break;
                    }
                    cutList = compareHotelRoomList.subList(threadSize * i, dataSize);
                } else {
                    cutList = compareHotelRoomList.subList(threadSize * i, threadSize * (i + 1));
                }
                final List<CompareHotelRoom> listStr = cutList;
                final String taskNum = String.valueOf(i + 1);
//            final List<CompareHotel> listStr = compareHotelList; //开启单线程
                task = new Callable<Integer>() {

                    @Override
                    public Integer call() throws Exception {

                        Thread.sleep(10);
                        compareHotelRoomBadByThread(taskNum, listStr);
                        return 1;
                    }
                };
                // 这里提交的任务容器列表和返回的Future列表存在顺序对应的关系
                tasks.add(task);
            }
        }
        List<Future<Integer>> results = exec.invokeAll(tasks);

        for (Future<Integer> future : results) {
            log.info("future.get()>>>" + future.get().toString());
            ret.append(future.get());
        }

        // 关闭线程池
        exec.shutdown();
        log.info("线程任务执行结束");

        return new Result<>("对比完成");
    }


    /**
     * 线程具体调用方法 --备用
     * @param compareHotelRoomList
     * @Author: Zhang·jz
     * @date: 2020/9/19
     */
    public void compareHotelRoomBadByThread(String taskNum,List<CompareHotelRoom> compareHotelRoomList){
        log.info("线程{}：开始进入compareHotelRoomBadByThread方法---->>>>",taskNum);
        //遍历
        compareHotelRoomList.forEach(e->{
            //获取携程的床型列表
            SwitchRoomBedInfo switchRoomBedInfo=new SwitchRoomBedInfo();
            switchRoomBedInfo.setRoomTypeId(Integer.valueOf(e.getSwitchHotelRoomId()));
            List<SwitchRoomBedInfo> switchRoomBedInfoList=switchRoomBedInfoMapper.select(switchRoomBedInfo);
            //获取美团的床型列表
            MtHotelRoomBedInfo mtHotelRoomBedInfo=new MtHotelRoomBedInfo();
            mtHotelRoomBedInfo.setMtRoomId(e.getMtHotelRoomId());
            List<MtHotelRoomBedInfo> mtHotelRoomBedInfos=mtHotelRoomBedInfoMapper.select(mtHotelRoomBedInfo);
            compareHotelRoomBedByList(switchRoomBedInfoList,mtHotelRoomBedInfos,e.getSwitchHotelId(),e.getSwitchHotelRoomId());
        });
        log.info("线程{}：compareHotelRoomBadByThread方法处理完成---->>>>",taskNum);
    }


    /**
     * 效验床型信息
     * @return
     * 1.获取已经匹配的房型id
     * 2.获取床型
     * 3.进行匹配
     * 4.保存入库
     */
    @Override
    public Result<Object> compareHotelRoomBed() {
        Map<String, CompareHotelRoom> compareHotelRooms= (Map<String, CompareHotelRoom>) redisService.get(CommonConstants.COMPARE_ROOM_ID);
        if(ObjectUtils.isEmpty(compareHotelRooms)){
            log.info("暂无匹配房型信息可对比");
           return new Result<>("暂无匹配房型信息可对比");
        }
        //遍历
        compareHotelRooms.values().forEach(e->{
            //获取携程的床型列表
            SwitchRoomBedInfo switchRoomBedInfo=new SwitchRoomBedInfo();
            switchRoomBedInfo.setRoomTypeId(Integer.valueOf(e.getSwitchHotelRoomId()));
            List<SwitchRoomBedInfo> switchRoomBedInfoList=switchRoomBedInfoMapper.select(switchRoomBedInfo);
            //获取美团的床型列表
            MtHotelRoomBedInfo mtHotelRoomBedInfo=new MtHotelRoomBedInfo();
            mtHotelRoomBedInfo.setMtRoomId(e.getMtHotelRoomId());
            List<MtHotelRoomBedInfo> mtHotelRoomBedInfos=mtHotelRoomBedInfoMapper.select(mtHotelRoomBedInfo);
            compareHotelRoomBedByList(switchRoomBedInfoList,mtHotelRoomBedInfos,e.getSwitchHotelId(),e.getSwitchHotelRoomId());
        });
        return new Result<>("对比完成");
    }
    /**
     * 对比酒店床型信息
     * 匹配规则 1床型名称 2.床的数量 3.床的米数
     * @param switchRoomBedInfoList
     * @param mtHotelRoomBedInfos
     * @param switchHotelId
     * @param switchHotelRoomId
     */
    private void compareHotelRoomBedByList(List<SwitchRoomBedInfo> switchRoomBedInfoList, List<MtHotelRoomBedInfo> mtHotelRoomBedInfos, Integer switchHotelId, String switchHotelRoomId) {
        if(switchRoomBedInfoList.size()<1||mtHotelRoomBedInfos.size()<1){
            log.info("美团和携程该房型的床型无数据，无法比较");
            return;
        }
        //构造表单保存数据
        List<CompareHotelRoomBed> compareHotelRoomBeds=new ArrayList<>();
        //用来判断数据是否效验过
        Map<String,Integer> hasEfficagy=new HashMap<>();
        //判断redis是否有效验数据
        if(redisService.exists(CommonConstants.SWITCH_MEITUAN_BED_ID)){
            hasEfficagy= (Map<String, Integer>) redisService.get(CommonConstants.SWITCH_MEITUAN_BED_ID);
        }

        //遍历床型列表
        for(SwitchRoomBedInfo switchRoomBedInfo:switchRoomBedInfoList){
            String bedName=switchRoomBedInfo.getName();
            //默认未效验
            int isCompare=0;
            String remark="";
            String key="";
            switchTab:for (MtHotelRoomBedInfo mtHotelRoomBedInfo:mtHotelRoomBedInfos){
                CompareHotelRoomBed compareHotelRoomBed=new CompareHotelRoomBed();
                compareHotelRoomBed.setId(String.valueOf(UUID.randomUUID()));
                compareHotelRoomBed.setCreateTime(new Date());
                compareHotelRoomBed.setModifyTime(new Date());
                //美团酒店id
                compareHotelRoomBed.setMtHotelId(mtHotelRoomBedInfo.getMtHotelId());
                //美团房型id
                compareHotelRoomBed.setMtHotelRoomId(mtHotelRoomBedInfo.getMtRoomId());
                //美团床型名称
                compareHotelRoomBed.setMtBedName(mtHotelRoomBedInfo.getMtBedType());
                //携程酒店id
                compareHotelRoomBed.setSwitchHotelId(switchHotelId);
                //携程房型id
                compareHotelRoomBed.setSwitchHotelRoomId(switchHotelRoomId);
                //携程床型名称
                compareHotelRoomBed.setSwitchBedName(bedName);

                //暂时用中文做key,消耗内存后面优化 携程床型名称+美团床型名称
                key=bedName+mtHotelRoomBedInfo.getMtBedType();

                //判断该组合是否效验过
                if(hasEfficagy.containsKey(key)){
                    log.info("携程床型{}--美团床型{}已经效验过",bedName,mtHotelRoomBedInfo.getMtBedType());
                    continue switchTab;
                }

                if(StringUtils.isEmpty(bedName)|| StringUtils.isEmpty(mtHotelRoomBedInfo.getMtBedType())){
                    log.info("床型为空，无法进行效验");
                    continue ;
                }
                //验证床型名称
                if(!CompareUtil.isSimilByBedName(bedName,mtHotelRoomBedInfo.getMtBedType())){
                    isCompare=2;
                    remark="床型名称不匹配";
                    log.info("携程床型{}--美团床型{}效验名称失败",bedName,mtHotelRoomBedInfo.getMtBedType());
                }else{
                    //床数
                    if(switchRoomBedInfo.getNumberOfBeds()!=Integer.valueOf(mtHotelRoomBedInfo.getMtBedCount())){
                        isCompare=2;
                        remark="床数不匹配";
                        log.info("携程床型{}--美团床型{}效验床数失败",switchRoomBedInfo.getNumberOfBeds(),mtHotelRoomBedInfo.getMtBedType());
                    }else{
                        //床宽
                        if(StringUtils.isEmpty(switchRoomBedInfo.getBedWidth())|| StringUtils.isEmpty(mtHotelRoomBedInfo.getMtBedDesc())){
                            log.info("床型宽度为空，无法进行效验");
                            continue ;
                        }

                        if(!switchRoomBedInfo.getBedWidth().equals(mtHotelRoomBedInfo.getMtBedDesc())){
                            isCompare=2;
                            remark="床宽不匹配";
                            log.info("携程床型{}--美团床型{}效验床款失败");
                        }else{
                            isCompare=1;
                            log.info("携程床型{}--美团床型{}已经效验成功",bedName,mtHotelRoomBedInfo.getMtBedType());
                            //过滤已经效验成功的数据
                            mtHotelRoomBedInfos.remove(mtHotelRoomBedInfo);
                        }
                    }
                }
                compareHotelRoomBed.setIsCompare(isCompare);
                compareHotelRoomBed.setRemark(remark);
                compareHotelRoomBeds.add(compareHotelRoomBed);
                //判断是否添加到效验集合
                if(!hasEfficagy.containsKey(key)){
                    hasEfficagy.put(key,isCompare);
                }
            }
        }
        if(compareHotelRoomBeds.size()>0){
            compareHotelRoomBedMapper.insertList(compareHotelRoomBeds);
        }
    }

    /**
     * 获取效验后的床型信息
     * @return
     */
    @Override
    public Result<Object> getCompareHotelRoomBedList() {
        List<CompareHotelRoomBed> compareHotelRoomBeds=compareHotelRoomBedMapper.selectAll();
        return new Result<>(compareHotelRoomBeds);
    }
}
